package sicnu.cs.ich.common.exceptions;

import com.qiniu.common.QiniuException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.mail.MailSendException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import sicnu.cs.ich.api.common.ResultInfo;
import sicnu.cs.ich.api.common.enums.ResultEnum;
import sicnu.cs.ich.common.exceptions.exception.*;
import sicnu.cs.ich.common.util.ResultInfoUtil;

import javax.crypto.BadPaddingException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.NoSuchElementException;
import java.util.Objects;

/**
 * @author CaiKe
 * 2021/9/7
 */
@ControllerAdvice
@Slf4j
public class RuntimeExceptionHandler {

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResultInfo<Void> handlerGlobalException(Exception exception) {
        log.error("Exception", exception);
        return ResultInfoUtil.buildError("服务器繁忙");
    }


    /**
     * 拦截参数校验的异常
     *
     * @param e 校验异常
     * @return 返回结果
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ResultInfo<Void> notValidExceptionHandle(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        Objects.requireNonNull(bindingResult.getFieldError());
        return ResultInfoUtil.buildError(ResultEnum.ERROR,
                bindingResult.getFieldError().getField() + " " + bindingResult.getFieldError().getDefaultMessage());
    }

    /**
     * 处理邮件发送失败的异常
     *
     * @param e 邮件发送失败异常
     * @return 返回结果
     */
    @ExceptionHandler(MailSendException.class)
    @ResponseBody
    public ResultInfo<Void> mailSendExceptionHandle(MailSendException e) {
        return ResultInfoUtil.buildError("邮件发送失败");
    }

    /**
     * 处理邮件发送失败的异常
     *
     * @param e 邮件发送失败异常
     * @return 返回结果
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    public ResultInfo<Void> httpMessageNotReadableExceptionHandle(HttpMessageNotReadableException e) {
        log.error("JSON格式错误：{}", e.getHttpInputMessage());
//        e.printStackTrace();
        return ResultInfoUtil.buildError("JSON格式错误");
    }

    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    public ResultInfo<Void> httpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e){
        return ResultInfoUtil.buildError("MediaTypeNotSupport");
    }
    @ExceptionHandler(BadPaddingException.class)
    @ResponseBody
    public ResultInfo<Void> keyEncryptException(BadPaddingException e) {
        return ResultInfoUtil.buildError("KEY DECRYPT ERROR");
    }
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    public ResultInfo<Void> methodNotSupportedExceptionHandle(HttpRequestMethodNotSupportedException e){
        return ResultInfoUtil.buildError("不支持该请求方式");
    }
    @ExceptionHandler(MultipartException.class)
    @ResponseBody
    public ResultInfo<Void> multipartExceptionHandle(){
        return ResultInfoUtil.buildError("文件缺失");
    }
    @ExceptionHandler({MethodArgumentTypeMismatchException.class,MissingServletRequestParameterException.class})
    @ResponseBody
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public ResultInfo<Void> methodArgumentMismatchException(MethodArgumentTypeMismatchException e){
        return ResultInfoUtil.buildError("缺少请求参数");
    }
    /**
     * Valid校验非json参数时返回的错误信息
     */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public ResultInfo<Void> bindExceptionHandle(BindException e){
        return ResultInfoUtil.buildError(Objects.requireNonNull(e.getFieldError()).getDefaultMessage());
    }
    @ExceptionHandler(NoSuchElementException.class)
    @ResponseBody
    public ResultInfo<Void> noSuchElementException(NoSuchElementException e){
        return ResultInfoUtil.buildError("无数据,"+e.getMessage());
    }
    @ExceptionHandler(QiniuException.class)
    @ResponseBody
    public ResultInfo<Void> qiniuExceptionHandle(QiniuException e){
        return ResultInfoUtil.buildError("文件上传失败请稍后重试");
    }
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    @ResponseBody
    public ResultInfo<Void> sQLIntegrityConstraintViolationException(SQLIntegrityConstraintViolationException e){
        return ResultInfoUtil.buildError("数据插入失败");
    }
    /**
     * 没有实名认证异常
     */
    @ExceptionHandler(UnRealNameAuthenticationException.class)
    @ResponseBody
    public ResultInfo<Void> unRealNameAuthenticationExceptionHandle(UnRealNameAuthenticationException e){
        return ResultInfoUtil.buildError(e.getMessage());
    }

    /**
     * 活动/号召时间异常
     * @param e
     * @return
     */
    @ExceptionHandler(ActivityTimeException.class)
    @ResponseBody
    public ResultInfo<Void> activityTimeExceptionHandle(ActivityTimeException e){
        return ResultInfoUtil.buildError(e.getMessage());
    }

    /**
     * 活动/号召状态异常
     * @param e
     * @return
     */
    @ExceptionHandler(ActivityStatusException.class)
    @ResponseBody
    public ResultInfo<Void> activityStatusExceptionHandle(ActivityStatusException e){
        return ResultInfoUtil.buildError(e.getMessage());
    }
    /**
     * 号召转活动的异常
     * @param e
     * @return
     */
    @ExceptionHandler(ActivityConverseException.class)
    @ResponseBody
    public ResultInfo<Void> activityConverseExceptionHandle(ActivityConverseException e){
        return ResultInfoUtil.buildError(e.getMessage());
    }

    @ExceptionHandler(MissingServletRequestPartException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResultInfo<Void> missingServletRequestPartException(MissingServletRequestPartException e){
        return ResultInfoUtil.buildError("文件缺失");
    }

    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public ResultInfo<Void> businessException(BusinessException e){
        return ResultInfoUtil.buildError(e.getMessage());
    }
    /**
     * 全局捕获运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public ResultInfo<Void> runtimeExceptionHandle(RuntimeException e){
        log.error("runtimeExceptionHandle打印异常",e);
        return ResultInfoUtil.buildError(e.getMessage());
    }
}